﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Infinity.Expressions;
using Infinity.Expressions.Loops;
using Infinity.Expressions.Commands;
using Infinity.Expressions.Core;
using Infinity.Expressions.Conditions;
using System.Reflection.Emit;
using System.Reflection;
using System.ComponentModel;

namespace Infinity.ExpressionDemo
{
	class Program
	{
		static void Main(string[] args)
		{
			var variable = Expression.Variable(typeof(int), "num");
			var assign = Expression.Block(
							new[] { variable },
							Expression.Assign(variable, Expression.Constant(10)));
			//Expression.Lambda<Action>(assign).Compile()();

			/*var block = new BlockBuilder();

			block.Add(Expression.Empty());
			block.Add(Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("Hello World!")));
			block.Add(

					DebugExpression.MakeDebugExpression(
					new ConditionBuilder()
					{
						Test = Expression.LessThan(Expression.Constant(10), Expression.Constant(41)),
						IfBlock = new BlockBuilder() { Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("Hello Conditional!")) },
						ElseBlock = new BlockBuilder()
					},
					Expression.Constant(true),
					Expression.Constant(true))
				);
			block.Add(Expression.Variable(typeof(int), "variable"));

			Expression.Lambda<Action>(block).Compile()();	 */

			/*var exp = Expression.Equal(Expression.Not(Expression.Constant(false)), Expression.Constant(false));
			var ret = System.Linq.Expressions.Expression.Lambda<Func<bool>>(exp, null).Compile(); */

			var var = new Variable() { Name = "number", Type = typeof(int), Value = 11 };

			/*var mainProgram = new MainProgram()
			{
				Command = new WhileLoop() { Condition = Expression.Constant(true), Body = new SkipCommand() }
			};*/

			/*var mainProgram = new MainProgram()
			{
				Command = new ForLoop()
				{
					Start = -2,
					End = 10,			
					By = 2,
					Body = new ExpressionCommand() { Command = Expression.Call(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) }), Expression.Constant("Hello World!")) }
				}
			};

			mainProgram.Variables.Add("num", new Variable() { Name = "num", Type = typeof(int), Value = 13 });
			mainProgram.Variables.Add("listNum", new Variable() { Name = "listNum", Type = typeof(List<int>), Value = new List<int>() { 1,2,3 } });

			var exp = mainProgram.ToExpression();
			Expression.Lambda<Action>(exp).Compile()();	*/

			//Lineáris keresés
			var linSearch = new MainProgram();
			linSearch.Variables.Add("k", typeof(int), 0);
			linSearch.Variables.Add("n", typeof(int), 10);
			linSearch.Variables.Add("d", typeof(int), 7);
			linSearch.Variables.Add("l", typeof(bool), false);
			linSearch.Body = new WhileLoop()
			{
				Condition = Expression.AndAlso(
									Expression.NotEqual(linSearch.Variables["k"].ToExpression(), linSearch.Variables["n"].ToExpression()),
									Expression.NotEqual(linSearch.Variables["l"].ToExpression(), Expression.Constant(true))),

				Body = new BlockCommand()
				{
						new ExpressionCommand(Expression.Assign(linSearch.Variables["l"].ToExpression(),
										  Expression.Equal(linSearch.Variables["k"].ToExpression(), linSearch.Variables["d"].ToExpression()))),
						new ExpressionCommand(Expression.AddAssign(linSearch.Variables["k"].ToExpression(), Expression.Constant(1)))
				}
			};
			linSearch.PreCondition = Expression.Constant(false);
			//var exp = Expression.Lambda<Func<object>>(linSearch.ToExpression()).Compile()();

			linSearch.Run();
			foreach (var item in linSearch.Variables)
			{
				Console.WriteLine("{0} : {1} ({2})", item.Key, item.Value.Value, item.Value.Type);
			}

			var summation = new MainProgram();
			summation.Variables.Add("k", typeof(int), 0);
			var list = new List<int>() { 1, 2, 3, 4, 4, 4, 7, 8, 9, 10 };
			summation.Variables.Add("list", typeof(int[]), list.ToArray());
			summation.Variables.Add("n", typeof(int), list.Count);
			summation.Variables.Add("d", typeof(int), 0);

			summation.Body = new ForLoop()
			{
				Start = (int)summation.Variables["k"].Value,
				End = (int)summation.Variables["n"].Value,
				By = 1
			};

			(summation.Body as ForLoop).Body = new ExpressionCommand(
						Expression.AddAssign(summation.Variables["d"].ToExpression(),
						Expression.ArrayIndex(
									summation.Variables["list"].ToExpression(),
									(summation.Body as ForLoop).LoopVariable.ToExpression() ))

					);

			summation.Run();
		}
	}
}